#include "gwbase/http_util.h"

#include <gwbase/base/logging.h>
#include <gwbase/base/util.h>

namespace dicom {

static bool NeedUrlEscape(char c) {
  if (c >= 'a' && c <= 'z') return false;
  if (c >= 'A' && c <= 'Z') return false;
  if (c >= '0' && c <= '9') return false;

  if (c == '_' || c == '.') return false;
  return true;
}

static char HexChar(int c) {
  static const char kHexChars[] = {"0123456789ABCDEF"};
  assert(c >= 0 && c <= 15);
  return kHexChars[c];
}

static void UrlEscapeChar(char c, char* buf) {
  *(buf++) = '%';
  *(buf++) = HexChar((c & 0xF0) >> 4);
  *(buf++) = HexChar(c & 0x0F);
  *(buf++) = '\0';
}

std::string UrlEscape(const std::string& raw) {
  std::string result;
  char buf[4];
  for (size_t i = 0; i < raw.size(); ++i) {
    char c = raw[i];
    if (!NeedUrlEscape(c)) {
      result.push_back(c);
    } else {
      UrlEscapeChar(c, buf);
      result.append(buf, 3);
    }
  }
  return result;
}

void AppendQueryString(std::string* qs, const std::string& name,
                       const std::string& value) {
  // append & if needed
  if (!qs->empty() && (*qs)[qs->size() - 1] != '&' &&
      (*qs)[qs->size() - 1] != '?')
    qs->push_back('&');
  qs->append(UrlEscape(name));
  qs->push_back('=');
  qs->append(UrlEscape(value));
}

void AppendQueryString(std::string* qs, const std::string& name,
                       int64_t value) {
  return AppendQueryString(qs, name, Fmt("%ld", value).str());
}
}
